// 用户认证API测试脚本
// 可以使用Node.js执行，或使用以下curl命令手动测试

const axios = require('axios');
const BASE_URL = 'http://127.0.0.1:3000/api/auth';

// 存储测试过程中获取的token
let accessToken = '';
let refreshToken = '';
let userId = '';

// 测试助手函数
async function runTest(name, fn) {
    console.log(`\n========== 测试: ${name} ==========`);
    try {
        await fn();
        console.log(`✅ 测试成功: ${name}`);
    } catch (error) {
        console.error(`❌ 测试失败: ${name}`);
        console.error(error.response ? error.response.data : error.message);
    }
}

// 1. 用户注册测试用例
async function testRegistration() {
    // 1.1 成功注册测试
    await runTest('注册成功', async () => {
        const response = await axios.post(`${BASE_URL}/register`, {
            username: `testuser_${Date.now()}`, // 使用时间戳避免用户名冲突
            password: 'password123',
            email: `test_${Date.now()}@example.com` // 使用时间戳避免邮箱冲突
        });

        console.log('响应状态码:', response.status);
        console.log('响应数据:', response.data);

        // 保存用户ID和token供后续测试使用
        userId = response.data.data.userId;
        accessToken = response.data.data.token;

        // 断言响应符合预期
        if (response.data.status !== 201 || !response.data.data.token) {
            throw new Error('响应格式不符合预期');
        }
    });

    // 1.2 用户名已存在测试
    await runTest('用户名已存在', async () => {
        const username = `duplicate_user_${Date.now()}`;

        // 先注册一个用户
        await axios.post(`${BASE_URL}/register`, {
            username,
            password: 'password123',
            email: `unique_${Date.now()}@example.com`
        });

        // 尝试使用相同用户名再次注册
        try {
            await axios.post(`${BASE_URL}/register`, {
                username,
                password: 'password123',
                email: `another_${Date.now()}@example.com`
            });
            throw new Error('应该抛出409错误但没有');
        } catch (error) {
            if (!error.response || error.response.status !== 409) {
                throw error;
            }
            console.log('正确返回409错误:', error.response.data);
        }
    });

    // 1.3 邮箱已被注册测试
    await runTest('邮箱已被注册', async () => {
        const email = `duplicate_email_${Date.now()}@example.com`;

        // 先注册一个用户
        await axios.post(`${BASE_URL}/register`, {
            username: `unique_user_${Date.now()}`,
            password: 'password123',
            email
        });

        // 尝试使用相同邮箱再次注册
        try {
            await axios.post(`${BASE_URL}/register`, {
                username: `another_user_${Date.now()}`,
                password: 'password123',
                email
            });
            throw new Error('应该抛出409错误但没有');
        } catch (error) {
            if (!error.response || error.response.status !== 409) {
                throw error;
            }
            console.log('正确返回409错误:', error.response.data);
        }
    });

    // 1.4 密码长度不足测试
    await runTest('密码长度不足', async () => {
        try {
            await axios.post(`${BASE_URL}/register`, {
                username: `short_password_user_${Date.now()}`,
                password: '12345', // 只有5位
                email: `short_pw_${Date.now()}@example.com`
            });
            throw new Error('应该抛出400错误但没有');
        } catch (error) {
            if (!error.response || error.response.status !== 400) {
                throw error;
            }
            console.log('正确返回400错误:', error.response.data);
        }
    });

    // 1.5 邮箱格式无效测试
    await runTest('邮箱格式无效', async () => {
        try {
            await axios.post(`${BASE_URL}/register`, {
                username: `invalid_email_user_${Date.now()}`,
                password: 'password123',
                email: 'invalid-email'
            });
            throw new Error('应该抛出400错误但没有');
        } catch (error) {
            if (!error.response || error.response.status !== 400) {
                throw error;
            }
            console.log('正确返回400错误:', error.response.data);
        }
    });
}

// 2. 用户登录测试用例
async function testLogin() {
    // 创建一个测试用户
    const testUsername = `login_test_user_${Date.now()}`;
    const testPassword = 'password123';

    await axios.post(`${BASE_URL}/register`, {
        username: testUsername,
        password: testPassword,
        email: `login_test_${Date.now()}@example.com`
    });

    // 2.1 登录成功测试
    await runTest('登录成功', async () => {
        const response = await axios.post(`${BASE_URL}/login`, {
            username: testUsername,
            password: testPassword
        });

        console.log('响应状态码:', response.status);
        console.log('响应数据:', response.data);

        // 保存token供后续测试使用
        accessToken = response.data.data.token;
        refreshToken = response.data.data.refreshToken;

        // 断言响应符合预期
        if (response.data.status !== 200 || !response.data.data.token || !response.data.data.refreshToken) {
            throw new Error('响应格式不符合预期');
        }
    });

    // 2.2 用户名不存在测试
    await runTest('用户名不存在', async () => {
        try {
            await axios.post(`${BASE_URL}/login`, {
                username: 'nonexistentuser',
                password: 'password123'
            });
            throw new Error('应该抛出401错误但没有');
        } catch (error) {
            if (!error.response || error.response.status !== 401) {
                throw error;
            }
            console.log('正确返回401错误:', error.response.data);
        }
    });

    // 2.3 密码错误测试
    await runTest('密码错误', async () => {
        try {
            await axios.post(`${BASE_URL}/login`, {
                username: testUsername,
                password: 'wrongpassword'
            });
            throw new Error('应该抛出401错误但没有');
        } catch (error) {
            if (!error.response || error.response.status !== 401) {
                throw error;
            }
            console.log('正确返回401错误:', error.response.data);
        }
    });

    // 2.4 缺少必要参数测试
    await runTest('缺少必要参数', async () => {
        try {
            await axios.post(`${BASE_URL}/login`, {
                username: testUsername
                // 缺少password
            });
            throw new Error('应该抛出400错误但没有');
        } catch (error) {
            if (!error.response || error.response.status !== 400) {
                throw error;
            }
            console.log('正确返回400错误:', error.response.data);
        }
    });
}

// 3. 令牌刷新测试用例
async function testTokenRefresh() {
    // 确保有登录令牌
    if (!accessToken || !refreshToken) {
        console.log('没有登录令牌，先执行登录测试');
        await testLogin();
    }

    // 3.1 成功刷新令牌测试
    await runTest('令牌刷新成功', async () => {
        const response = await axios.post(`${BASE_URL}/refresh`, {}, {
            headers: {
                'Authorization': `Bearer ${accessToken}`,
                'Refresh-Token': refreshToken
            }
        });

        console.log('响应状态码:', response.status);
        console.log('响应数据:', response.data);

        // 更新token
        accessToken = response.data.data.token;

        // 断言响应符合预期
        if (response.data.status !== 200 || !response.data.data.token) {
            throw new Error('响应格式不符合预期');
        }
    });

    // 3.2 缺少授权头测试
    await runTest('缺少授权头', async () => {
        try {
            await axios.post(`${BASE_URL}/refresh`, {}, {
                headers: {
                    'Refresh-Token': refreshToken
                    // 缺少Authorization
                }
            });
            throw new Error('应该抛出401错误但没有');
        } catch (error) {
            if (!error.response || error.response.status !== 401) {
                throw error;
            }
            console.log('正确返回401错误:', error.response.data);
        }
    });

    // 3.3 缺少刷新令牌测试
    await runTest('缺少刷新令牌', async () => {
        try {
            await axios.post(`${BASE_URL}/refresh`, {}, {
                headers: {
                    'Authorization': `Bearer ${accessToken}`
                    // 缺少Refresh-Token
                }
            });
            throw new Error('应该抛出401错误但没有');
        } catch (error) {
            if (!error.response || error.response.status !== 401) {
                throw error;
            }
            console.log('正确返回401错误:', error.response.data);
        }
    });

    // 3.4 刷新令牌无效测试
    await runTest('刷新令牌无效', async () => {
        try {
            await axios.post(`${BASE_URL}/refresh`, {}, {
                headers: {
                    'Authorization': `Bearer ${accessToken}`,
                    'Refresh-Token': 'invalid.refresh.token'
                }
            });
            throw new Error('应该抛出401错误但没有');
        } catch (error) {
            if (!error.response || error.response.status !== 401) {
                throw error;
            }
            console.log('正确返回401错误:', error.response.data);
        }
    });
}

// 运行所有测试
async function runAllTests() {
    console.log('===== 开始 API 测试 =====');
    await testRegistration();
    await testLogin();
    await testTokenRefresh();
    console.log('\n===== 所有测试完成 =====');
}

// 执行测试
runAllTests().catch(console.error); 